package de.preamp.clients.java.data;

import java.awt.datatransfer.DataFlavor;
import java.io.IOException;
import java.util.Collection;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.swing.ImageIcon;

import org.json.JSONException;

import de.preamp.clients.java.net.ServerConnection;
import de.preamp.clients.java.net.ServerConnectionImpl;
import de.preamp.clients.java.utils.ImageCache;

/**
 * A class modeling a musical artist who has published albums under his name.
 * Valid artists are those in the id3 TPE1 fields of the music files in the
 * database.
 * 
 * @author André Stannek
 * @version 2010-03-21
 * @see AbstractDBItem
 * @see Album
 * @see Track
 */
public class Artist extends AbstractDBItem implements Updatetable,
	Comparable<Artist>
{
    /**
     * the artists name.
     */
    private final transient String artistName;

    /**
     * the albums made by this artist which are available.
     */
    private transient SortedSet<Album> albums;

    /**
     * 
     */
    private transient ImageIcon picture;

    /**
     * Constructor for a new artist with a name from the id3 TPE1 field.
     * 
     * @param artist
     *            the name of the artist from the id3 TPE1 field
     */
    public Artist(final String artist)
    {
	super();
this.artistName = artist;
this.albums = new TreeSet<Album>();
    }

    /**
     * Returns the name of the artist from the id3 TPE1 field.
     * 
     * @return the name of the artist from the id3 TPE1 field.
     */
    public final String getName()
    {
	return this.artistName;
    }

    /**
     * Gets all albums available for this artist from the server and adds their
     * tracks. No temprary information is stored so the next call will always
     * return the present information in the database.
     * 
     * @return the albums made by this artist which are available with all of
     *         their tracks
     * @throws JSONException
     *             if server returned a broken value
     * @throws IOException
     *             if connection to server was impossible
     */
    public final SortedSet<Album> getAlbums() throws IOException, JSONException
    {
	update();
	return this.albums;
    }

    /**
     * Returns an image for this artist. Try invoking
     * {@link Artist#loadPicture()} if Picture is <code>null</code>.
     * 
     * @return a picture of this artist or null if none available or loaded.
     */
    public final ImageIcon getPicture()
    {
	return this.picture;
    }

    /**
     * Tries to load a picture of this artist from the image cache.
     * 
     * @see de.preamp.clients.java.utils.ImageCache#getArtistImage(String)
     */
    public final void loadPicture()
    {
	this.picture = ImageCache.getArtistImage(artistName);
	fireChangeListeners();
    }

    @Override
    public final void update() throws IOException, JSONException
    {
	final ServerConnection server = new ServerConnectionImpl();
	final Collection<Track> tracks = server.getFilesByArtist(this.artistName);
	this.albums = new TreeSet<Album>();
	for (final Track track : tracks)
	{
	    this.albums.add(new Album(track.getAlbum(), track.getCover()));
	}
	for (final Album album : this.albums)
	{
	    for (final Track track : tracks)
	    {
		album.addTrack(track);
	    }
	}
	fireChangeListeners();
    }

    @Override
    public final int hashCode()
    {
	return this.artistName.hashCode();
    }

    @Override
    public final boolean equals(final Object object)
    {
	boolean result = false;
	if (object instanceof Artist)
	{
	    final Artist artist = (Artist) object;
	    if (this.artistName.equals(artist.artistName))
	    {
		result = true;
	    }
	}
	return result;
    }

    @Override
    public final int compareTo(final Artist object)
    {
	return this.artistName.compareTo(object.getName());
    }

    @Override
    public final String toString()
    {
	return this.artistName;
    }

    @Override
    public final DataFlavor[] getTransferDataFlavors()
    {
	return new DataFlavor[] { new DataFlavor(
		DataFlavor.javaJVMLocalObjectMimeType + "; class="
			+ getClass().getName(), "Artist") };
    }

    @Override
    public final SortedSet<Track> getTracks()
    {
	final SortedSet<Track> result = new TreeSet<Track>();
	for (final Album album : albums)
	{
	    result.addAll(album.getTracks());
	}
	return result;
    }
}
